# -*- coding: utf-8 -*-

import numpy as np

class unsu_module(object):
    '''
    这是非监督学习，自定义公式的类。
    '''
    def __init__(self):
        self.heart_list = []
        self.sum_list, self.Cd_score_list_heart = [], []
        self.qinmi_list = []  
        self.qinmi_score_list, self.Cd_score_list_qinmi = [], []
        
    def heart(self, x, c, cd):
        '''
        该函数用于非监督学习中构建心情系统
        input:
             x——分数向量（包括心情与亲密度分数）
             c——向量标注，其中0代表是亲密度函数的分数，1代表心情函数的分数
             cd——向量类别标注，写出c中每个向量是属于哪个领域，1代表语音，2代表表情，3代表行为,4代表机器人本身环境
        output：
             

        '''     
        le = c.count(1) # 心情值数量
        if isinstance(x[0],int):#如果只有一行测试数据
            #heart_list = [ ]
            #计算心情向量
            for i in range(len(c)):
                if c[i] == 1:
                    self.heart_list.append(x[i])
            
            #计算类别向量
            l1, l2, l3, l4 = 0, 0, 0, 0
            for l in range(le, len(cd)):
                if cd[l] == 1: l1 = l1 + x[l]
                if cd[l] == 2: l2 = l2 + x[l]
                if cd[l] == 3: l3 = l3 + x[l]
                if cd[l] == 4: l4 = l4 + x[l]
            self.Cd_score_heart = [l1, l2, l3, l4]
            
            self.heart_num = sum(self.heart_list)
            print('心情向量：', self.heart_list, '\n',
                  '心情值：', self.heart_num, '\n',
                  '心情特征向量：', self.Cd_score_heart)
            
        else:#有n行测试数据
            self.heart_list = np.zeros([len(x), le])
            #sum_list, Cd_score_list = [], []
            for k in range(len(x)):
                j_vec = x[k]
                j = 0
                #计算心情值向量与心情list
                for i in range(len(c)):
                    if c[i] == 1:
                        self.heart_list[k, j] = j_vec[i]
                        j = j + 1
                self.sum_list.append(sum(self.heart_list[k]))
                #计算心情特征list
                l1, l2, l3, l4 = 0, 0, 0, 0
                for l in range(le, len(cd)):
                    if cd[l] == 1: l1 = l1 + j_vec[l]
                    if cd[l] == 2: l2 = l2 + j_vec[l]
                    if cd[l] == 3: l3 = l3 + j_vec[l]
                    if cd[l] == 4: l4 = l4 + j_vec[l]
                Cd_score = [l1, l2, l3, l4]
                self.Cd_score_list_heart.append(Cd_score)
            print('心情list：', self.heart_list, '\n',
                  '心情值向量：', self.sum_list, '\n',
                  '心情特征list：', self.Cd_score_list_heart)
            
    def qinmi(self, x, c, cd, p):
        '''
        该函数用于构建亲密系统（多元线性方法）
        input:
             x——分数向量（包括心情与亲密度分数）
             c——向量标注，其中0代表是亲密度函数的分数，1代表心情函数的分数
             cd——向量类别标注，写出c中每个向量是属于哪个领域，1代表语音，2代表表情，3代表行为,4代表机器人本身环境
             p——亲密度每个特征所占的维度。
        output：

        '''
        le = c.count(0) # 亲密值数量
        if isinstance(x[0],int):#如果只有一行测试数据
            self.qinmi_list = [ ]
            #计算亲密度向量
            for i in range(len(c)):
                if c[i] == 0:
                    self.qinmi_list.append(x[i])
            #计算亲密度        
            qinmidu = 0
            for j in range(len(p)):
                qinmidu  = qinmidu + self.qinmi_list[j] * p[j]
            #计算特征向量
            l1, l2, l3, l4 = 0, 0, 0, 0
            for l in range(le):
                if cd[l] == 1: l1 = l1 + x[l]
                if cd[l] == 2: l2 = l2 + x[l]
                if cd[l] == 3: l3 = l3 + x[l]
                if cd[l] == 4: l4 = l4 + x[l]
            self.Cd_score_qinmi = [l1, l2, l3, l4]
            
            self.qinmi_num = qinmidu
            print('亲密度向量：', self.qinmi_list, '\n',
                  '亲密度：', self.qinmi_num, '\n',
                  '亲密特征向量：', self.Cd_score_qinmi)
            
        else:#有n行测试数据
            self.qinmi_list = np.zeros([len(x), le])
            #qinmi_score_list, Cd_score_list = [], []
            
            for k in range(len(x)):
                j_vec = x[k]
                j = 0
                #计算亲密度list
                for i in range(len(c)):
                    if c[i] == 0:
                        self.qinmi_list[k, j] = j_vec[i]
                        j = j + 1
                #计算特征向量                       
                l1, l2, l3, l4 = 0, 0, 0, 0
                for l in range(le):
                    if cd[l] == 1: l1 = l1 + j_vec[l]
                    if cd[l] == 2: l2 = l2 + j_vec[l]
                    if cd[l] == 3: l3 = l3 + j_vec[l]
                    if cd[l] == 4: l4 = l4 + j_vec[l]
                Cd_score2 = [l1, l2, l3, l4]
                self.Cd_score_list_qinmi.append(Cd_score2)
            #计算亲密度向量
            for qinmi_vec in self.qinmi_list:
                    qinmidu = 0
                    for m in range(len(p)):
                        qinmidu = qinmidu + qinmi_vec[m] * p[m]
                    self.qinmi_score_list.append(qinmidu)
                    
            print('亲密list：', self.qinmi_list, '\n',
                  '亲密度向量：', self.qinmi_score_list, '\n',
                  '特征list：', self.Cd_score_list_qinmi)
    def list_add(self, a, b):
        '''
        该函数用于list元素相加，a与b是相同维度的一维list。
        '''
        re = np.zeros([1,len(a)])
        for i in range(len(a)):
            re[0,i] = a[i] + b[i]
        return re         
    
    def heart_qinmi(self, x, c, cd, p):
        '''
        该函数用于结合心情函数与亲密度函数
        '''
        self.heart(x, c, cd)
        self.qinmi(x, c, cd, p)
        if isinstance(x[0],int):#如果只有一行测试数据
            #计算分数
            if self.qinmi_num < 5: y = 0.3*self.heart_num + 0.7 * self.qinmi_num
            elif self.heart_num < 0 :y = 0.7*self.heart_num + 0.3 * self.qinmi_num
            else : y = 0.5*self.heart_num + 0.5 * self.qinmi_num
            #计算反馈分数
            if y < 0 :back_level = 1
            elif y <= 5: back_level = 2
            else :back_level = 3
            #计算心情结合亲密的特征list
            back_feature = self.list_add(self.Cd_score_heart , self.Cd_score_qinmi)
            
            print('分数：', y,  '\n',
                  '反馈级别：', back_level, '\n',
                  '结合特征：', back_feature)
    
            
        else:#有多行测试数据  
            y_list = np.zeros([1,len(x)])
            back_level_list = np.zeros([1,len(x)])
            back_feature_list = []
            for i in range(len(x)):
                heart_vec = self.heart_list[i]
                heart_score = self.sum_list[i]
                qinmi_vec = self.qinmi_list[i]
                qinmi_score = self.qinmi_score_list[i]
                heart_cd_vec = self.Cd_score_list_heart[i]
                qinmi_cd_vec = self.Cd_score_list_qinmi[i]
                #计算分数
                if qinmi_score < 5: y = 0.3*heart_score + 0.7 * qinmi_score
                elif heart_score < 0 :y = 0.7*heart_score + 0.3 * qinmi_score
                else : y = 0.5 * heart_score + 0.5 * qinmi_score
                y_list[0,i] = y
                #计算反馈分数
                if y < 0 :back_level = 1
                elif y <= 5: back_level = 2
                else :back_level = 3
                back_level_list[0, i] = back_level
                
                #计算心情结合亲密的特征list
                back_feature = self.list_add(heart_cd_vec, qinmi_cd_vec)
                back_feature_list.append(back_feature[0])
            
            print('分数list：', y_list,  '\n',
                  '反馈级别list：', back_level_list, '\n',
                  '结合特征list：', back_feature_list)
            #print(heart_cd_vec, qinmi_cd_vec, )
                
                
                
                
        
        
